package com.w2e.user.controller;


import com.aliyun.captcha20230305.models.VerifyIntelligentCaptchaRequest;
import com.aliyun.captcha20230305.models.VerifyIntelligentCaptchaResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.w2e.common.utils.RedisUtils;
import com.w2e.common.utils.UserContext;
import com.w2e.user.entity.User;
import com.w2e.user.mapper.UserMapper;
import com.w2e.user.service.IUserService;
import com.w2e.user.utils.JwtUtils;
import com.w2e.user.vo.ResultVo;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import com.w2e.common.utils.Result;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author yyyl
 * @since 2024-06-13
 */
@RestController
@RequestMapping("/users")
public class UserController {

    @Resource
    private UserMapper userMapper;

    @Resource
    private JwtUtils jwtUtils;

    @Resource
    private IUserService userService;

    @Resource
    private RedisTemplate redisTemplate;

    private static final String EMAIL_PATTERN = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}$";
    private static final String PHONE_PATTERN = "^1[3-9]\\d{9}$";

    private static final String  ACCESS_KEY_ID = "LTAI5tL4CUK6kW9YYxDE2yQg";
    private static final String  ACCESS_KEY_SECRET = "FspYbGeSBqAQJ9tWED2YOQ3B1mKp0l";

    public static String getEnvProperty(String propertyName) throws Exception {
        if (propertyName.equals("ACCESS_KEY_ID")){
            return ACCESS_KEY_ID;
        }else if (propertyName.equals("ACCESS_KEY_SECRET")){
            return ACCESS_KEY_SECRET;
        }
        return "null";
    }


    public static com.aliyun.dysmsapi20170525.Client createClient() throws Exception {
        // 工程代码泄露可能会导致 AccessKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考。
        // 建议使用更安全的 STS 方式，更多鉴权访问方式请参见：https://help.aliyun.com/document_detail/378657.html。
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                // 必填，请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
                .setAccessKeyId(ACCESS_KEY_ID)
                // 必填，请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
                .setAccessKeySecret(ACCESS_KEY_SECRET);
        // Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi
        config.endpoint = "dysmsapi.aliyuncs.com";
        return new com.aliyun.dysmsapi20170525.Client(config);
    }


    @PostMapping("login")
    public ResultVo login(@RequestBody Map<String, String> loginData) throws Exception {
        String captchaVerifyParam = loginData.get("captchaVerifyParam");
        String account = loginData.get("account");
        String pwd = loginData.get("pwd");

        // ====================== 1. 初始化配置 ======================
        Config config = new Config();
        // 设置您的AccessKey ID 和 AccessKey Secret。
        // getEnvProperty只是个示例方法，需要您自己实现AccessKey ID 和 AccessKey Secret安全的获取方式。
        config.accessKeyId = UserController.getEnvProperty("ACCESS_KEY_ID");
        config.accessKeySecret = UserController.getEnvProperty("ACCESS_KEY_SECRET");
        //设置请求地址 国内调用地址 captcha.cn-shanghai.aliyuncs.com
        config.endpoint = "captcha.cn-shanghai.aliyuncs.com";
        // 设置连接超时为5000毫秒
        config.connectTimeout = 5000;
        // 设置读超时为5000毫秒
        config.readTimeout = 5000;
        // ====================== 2. 初始化客户端（实际生产代码中建议复用client） ======================
        com.aliyun.captcha20230305.Client client = new com.aliyun.captcha20230305.Client(config);
        // 创建APi请求
        VerifyIntelligentCaptchaRequest request = new VerifyIntelligentCaptchaRequest();
        // 本次验证的场景ID，建议传入，防止前端被篡改场景
        request.sceneId = "1g30ua16";
        // 前端传来的验证参数 CaptchaVerifyParam
        request.captchaVerifyParam = captchaVerifyParam;
        // ====================== 3. 发起请求） ======================
        Boolean captchaVerifyResult = false;
        try {
            VerifyIntelligentCaptchaResponse resp = client.verifyIntelligentCaptcha(request);
            // 建议使用您系统中的日志组件，打印返回
            // 获取验证码验证结果（请注意判空），将结果返回给前端。出现异常建议认为验证通过，优先保证业务可用，然后尽快排查异常原因。
            captchaVerifyResult = resp.body.result.verifyResult;
            // 原因code
            String verifyCode = resp.body.result.verifyCode;
        } catch (TeaException error) {
            // 建议使用您系统中的日志组件，打印异常
            // 出现异常建议认为验证通过，优先保证业务可用，然后尽快排查异常原因。
//            captchaVerifyResult = true;
            System.err.println("TeaException occurred: " + error.getMessage());
            error.printStackTrace();
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            // 建议使用您系统中的日志组件，打印异常
            // 出现异常建议认为验证通过，优先保证业务可用，然后尽快排查异常原因。
//            captchaVerifyResult = true;
            System.err.println("Exception occurred: " + error.getMessage());
            error.printStackTrace();
        }

        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        User user;
        if (account.matches(PHONE_PATTERN)) {
            lqw.eq(User::getPhone,account);
            user = userMapper.selectOne(lqw);
        }else if (account.matches(EMAIL_PATTERN)){
            lqw.eq(User::getEmail,account);
            user = userMapper.selectOne(lqw);
        }else{
            lqw.eq(User::getUsername,account);
            user = userMapper.selectOne(lqw);
        }

        if (user != null){
            if (user.getPassword().equals(pwd)){
//                session.setAttribute("loginedUser",user);
                //生成jwt
                String token = jwtUtils.createToken(user.getId());
                //存入redis
                String id = user.getId().toString();
                redisTemplate.opsForValue().set(id,token);
                //设置一小时过期时间
                redisTemplate.expire(id,1,TimeUnit.HOURS);

                return new ResultVo(200,token,captchaVerifyResult,"登陆成功");
            }else{
                return new ResultVo(500,null,captchaVerifyResult,"账号或者密码错误，请重新输入！");
            }
        }else{
            return new ResultVo(404,null,captchaVerifyResult,"用户不存在，请注册一个账号！");
        }
    }


    @GetMapping("register/code")
    private Result getVerifyCode(String phone,HttpSession session) throws Exception {
        // 生成6位随机验证码
        Random rd = new Random();
        StringBuilder codeBuilder = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            codeBuilder.append(rd.nextInt(10));
        }
        String code = codeBuilder.toString();

        com.aliyun.dysmsapi20170525.Client client = UserController.createClient();
        com.aliyun.dysmsapi20170525.models.SendSmsRequest sendSmsRequest = new com.aliyun.dysmsapi20170525.models.SendSmsRequest()
                .setSignName("去哪儿网")
                .setTemplateCode("SMS_468290581")
                .setPhoneNumbers(phone)
                .setTemplateParam("{\"code\":\"" + code + "\"}");
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        session.setAttribute("verifyCode",code);
        session.setMaxInactiveInterval(300); //设置验证码5分钟过期
        try {
            // 复制代码运行请自行打印 API 的返回值
            client.sendSmsWithOptions(sendSmsRequest, runtime);
        } catch (TeaException error) {
            // 此处仅做打印展示，请谨慎对待异常处理，在工程项目中切勿直接忽略异常。
            // 错误 message
            System.out.println(error.getMessage());
            // 诊断地址
            System.out.println(error.getData().get("Recommend"));
            com.aliyun.teautil.Common.assertAsString(error.message);
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            // 此处仅做打印展示，请谨慎对待异常处理，在工程项目中切勿直接忽略异常。
            // 错误 message
            System.out.println(error.getMessage());
            // 诊断地址
            System.out.println(error.getData().get("Recommend"));
            com.aliyun.teautil.Common.assertAsString(error.message);
        }

        return new Result(200,null,"短信已经发送，请注意查看");
    }


    @PostMapping("register/register")
    public Result register(@RequestBody Map<String,String> map,HttpSession session){
        String phone = map.get("phone");
        String code = map.get("code");
        String pwd = map.get("pwd");
        String verifyCode = session.getAttribute("verifyCode").toString();
        if (!verifyCode.equals(code)){
            return new Result(500,null,"验证码错误！");
        }

        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper();
        lqw.eq(User::getPhone, phone);
        User user = userMapper.selectOne(lqw);
        if (user != null){
            return new Result(500,null,"用户"+user.getUsername()+"已经存在！");
        }else{
            user = new User();
            user.setPhone(phone);
            user.setPassword(pwd);
            user.setUsername("用户"+ UUID.randomUUID().toString().substring(0,6));
            user.setRegisterDate(LocalDateTime.now());
            user.setAvatar("images/moren.jpg");
            userMapper.insert(user);
            session.removeAttribute("verifyCode");
            return new Result(200,null,"注册成功，快点登陆吧");
        }

    }

    @GetMapping("isLogin")
    public Result isLogin(){
        User user = null;
//        if (session.getAttribute("loginedUser") == null ){
//            return new Result(500,null,"");
//        }else{
//            user = (User) session.getAttribute("loginedUser");
//            return new Result(200,user,"");
//        }
        Integer id = UserContext.getUser();
        user = userMapper.selectById(id);
        return new Result(200,user,"");
    }

    @GetMapping("isExist")
    public Result isExist(@RequestParam("userId")Integer userId){
        if (userId == null){
            return new Result(500,null,"用户id不能为null！");
        }else{
            User user = userMapper.selectById(userId);
            if (user != null){
                return new Result(200,null,"用户id存在");
            }else{
                return new Result(500,null,"用户id不存在,请创建一个新用户！");
            }
        }
    }

    @GetMapping("getByTid")
    public Result getByTid(@RequestParam("id")Integer id){
        User user = userService.getById(id);
        return new Result(200,user,"");
    }

    @GetMapping("loginout")
    public Result loginout(){
        return new Result(200,null,"");
    }

    @GetMapping("getById")
    public Result getById(@RequestParam("id")Integer id){
        User user = userMapper.selectById(id);
        return new Result(200,user,"");
    }


}
